#include "WindowsWindow.h"

int FWindowsWindow::ScreenInit(int Width, int Height, const TCHAR* Title)
{
    WNDCLASS WC = { CS_BYTEALIGNCLIENT,
    (WNDPROC)ScreenEvents,
        0,
        0,
        0,
        NULL,
        NULL,
        NULL,
        NULL,
        _T("SCREEN3.1415926")
    };
    BITMAPINFO BitMapInfo = { {sizeof(BITMAPINFOHEADER), Width, -Height, 1, 32, BI_RGB, Width * Height * 4, 0, 0, 0, 0 }};
    RECT Rect = { 0, 0, Width, Height };
    int wx, wy, sx, sy;
    LPVOID FrameBufferPtr;
    HDC HDC;

    ScreenClose();

    WC.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    WC.hInstance = GetModuleHandle(NULL);
    WC.hCursor = LoadCursor(NULL, IDC_ARROW);
    if (!RegisterClass(&WC)) {
        return -1;
    }

    ScreenHandler = CreateWindow(_T("SCREEN3.1415926"), Title,
        WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
        0, 0, 0, 0,
        NULL, NULL,
        WC.hInstance, NULL);
    if (ScreenHandler == NULL) {
        return -2;
    }

    HDC = GetDC(ScreenHandler);
    ScreenDC = CreateCompatibleDC(HDC);
    ReleaseDC(ScreenHandler, HDC);

    ScreenDIB = CreateDIBSection(ScreenDC, &BitMapInfo, DIB_RGB_COLORS, &FrameBufferPtr, 0, 0);
    if (ScreenDIB == NULL) {
        return -3;
    }

    ScreenOld = (HBITMAP)SelectObject(ScreenDC, ScreenDIB);
    ScreenFrameBuffer = (unsigned char*)FrameBufferPtr;
    ScreenWidth = Width;
    ScreenHeight = Height;
    ScreenPitch = Width * 4;

    AdjustWindowRect(&Rect, GetWindowLong(ScreenHandler, GWL_STYLE), 0);
    wx = Rect.right - Rect.left;
    wy = Rect.bottom - Rect.top;
    sx = (GetSystemMetrics(SM_CXSCREEN) - wx) / 2;
    sy = (GetSystemMetrics(SM_CYSCREEN) - wy) / 2;
    if (sy < 0) {
        sy = 0;
    }
    SetWindowPos(ScreenHandler, NULL, sx, sy, wx, wy, (SWP_NOCOPYBITS | SWP_NOZORDER | SWP_SHOWWINDOW));
    SetForegroundWindow(ScreenHandler);

    ShowWindow(ScreenHandler, SW_NORMAL);
    ScreenDispatch();

    memset(ScreenFrameBuffer, 0, Width * Height * 4);

    return 0;
}

int FWindowsWindow::ScreenClose()
{
    if (ScreenDC) {
        if (ScreenOld) {
            SelectObject(ScreenDC, ScreenOld);
            ScreenOld = NULL;
        }
        DeleteDC(ScreenDC);
        ScreenDC = NULL;
    }
    if (ScreenDIB) {
        DeleteObject(ScreenDIB);
        ScreenDIB = NULL;
    }
    if (ScreenHandler) {
        CloseWindow(ScreenHandler);
    }
    return 0;
}

void FWindowsWindow::ScreenDispatch()
{
    MSG Msg;
    while (1) {
        if (!PeekMessage(&Msg, NULL, 0, 0, PM_NOREMOVE)) {
            break;
        }
        if (!GetMessage(&Msg, NULL, 0, 0)) {
            break;
        }
        DispatchMessage(&Msg);
    }
}

void FWindowsWindow::ScreenUpdate()
{
    HDC HDC = GetDC(ScreenHandler);
    BitBlt(HDC, 0, 0, ScreenWidth, ScreenHeight, ScreenDC, 0, 0, SRCCOPY);
    ReleaseDC(ScreenHandler ,HDC);
    ScreenDispatch();
}
